package com.example.springblog.utils;

import com.example.springblog.constant.Constants;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cglib.core.ClassInfo;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.util.Date;
import java.util.Map;


@Slf4j
public class JwtUtils {
    /*
    ↓↓↓这三行，有的地方，还是不太明白。。。
    明白了
     */
    private static final long JWT_EXPIRATION = 60 * 60 * 1000 * 10;//1小时（毫秒）“保质时长”
    private static final String keyPre = "hpHu5nNpPizHFnI2kewOqm3T6uvqyhcALZQgqmJF7CE=";//keyPre，密钥，用于生成 安全密钥，即：签名key
                                                                                        //        对字符数和字符类型有要求，采用另一个工具类生成后，粘过来的

    private static final Key key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(keyPre));//key，安全密钥，也就是签名，用于生成token和对应的token校验



    /**genJwtToken    genToken
     * 生成  token/令牌/Jwt
     */
    public static String genJwtToken(Map<String, Object> claim) {
        //
        String token = Jwts.builder().setClaims(claim)
                .setExpiration(new Date(System.currentTimeMillis() + JWT_EXPIRATION))//过期时间（点）
                .signWith(key)//设置签名
                .compact();//将前边设置的几个信息拼接、组合在一起
        System.out.println("token:" + token);//打印出来看看这个token

        return token;
    }

    /**
     * 校验token
     * Claims 为null，表示校验失败
     */
    public static Claims parseToken(String token) {
        JwtParser build = Jwts.parserBuilder().setSigningKey(key).build();//根据刚才生成token的签名，创建 解析器（以刚才的key为参数）
                                                                          // 这是一种写法
                                                                          //另一种写法：JwtParseBuilder jwtParserBuilder = Jwts.parserBuilder().setSigningKey(key)不过后续的使用上也略有差别
        log.info("前端返回，并即将被解析的token@@@:{}",token);
        Claims claims = null;
        try{
            claims = build.parseClaimsJws(token).getBody();
        }catch (Exception e){
            log.error("解析token失败，token1：{}",token);
            return null;//这里，需要保证逻辑上，失败claims就是null，成功就不是null！
        }
        return claims;
    }



    public static Integer getIdByToken(String token) {
        Claims claims = parseToken(token);
        if(claims != null){
            Integer userId = (Integer) claims.get(Constants.TOKEN_ID);
            if(userId > 0){
                return userId;
            }
        }
        return null;
    }
}
